import time
import datetime
import logging
import logging.handlers
import socket
import inspect
import base64
import random
from enum import Enum
from Crypto.Cipher import AES

class Node:
    ip = None
    port = None
    uri = None
    status = 0
    fail = 0
    last = 0
    etc = {}
    session = None

class Module:
    etc = {}
    ping = True
    nodes = []
    https_nodes = []
    require = []


class AEScoder:
    @classmethod
    def encrypt(cls, key, data):
        key = base64.b16decode(str.upper(key))
        if len(key) != 16:
            return None
        while len(data) % 16 != 0:
            data += (16 - len(data) % 16) * chr(16 - len(data) % 16)
        data = str.encode(data)
        cipher = AES.new(key, AES.MODE_ECB)
        encrpted_data = cipher.encrypt(data)
        base16_data = str(base64.b16encode(encrpted_data), "utf-8")
        return base16_data

    @classmethod
    def decrypt(cls, key, base16_data):
        key = base64.b16decode(str.upper(key))
        if len(key) != 16:
            return None
        encrpted_data = base64.b16decode(str.upper(base16_data))
        def unpad(s): return s[0:-s[-1]]
        cipher = AES.new(key, AES.MODE_ECB)
        decrypted_ata = unpad(cipher.decrypt(encrpted_data))
        return decrypted_ata.decode('utf-8')


class AuthverManager:
    def __init__(self):
        self.__authver__ = {}
        self.__authver__["0"] = "e9a3aae2e27942ed565a0f70a43cdb6d"
        self.__authver__["1"] = "d00fe14b205c01a8b2eb4afe65fbae71"

    def generate_authver_key(self):
        key_index = random.randint(0, 1)
        print("index is ", key_index)
        if key_index == 0 :
            return ("0", self.__authver__["0"])
        else :
            return ("1", self.__authver__["1"])
    
    def get_key(self, authver):
        print("require ver=", authver)
        if authver in self.__authver__:
            print("key=", self.__authver__[authver])
            return self.__authver__[authver]
        print("has no key")
        return None

class Utils:
    @classmethod
    def check_keys(cls, json, keys):
        for i in keys:
            if i not in json:
                return False
        return True
    @classmethod
    def get_host_ip(cls):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.connect(('8.8.8.8', 80))
            ip = s.getsockname()[0]
        finally:
            s.close()
        return ip
    @classmethod
    def init_binlogging(cls, process_name, logger, lvl=logging.INFO, folder="log"):
        fmt_str = '%(message)s'
        logging.basicConfig()

        fileshandle = logging.handlers.TimedRotatingFileHandler("./%s/%s.log" % (folder,process_name), when='H', interval=1, backupCount=24*100)
        fileshandle.suffix = "%Y%m%d%H"
        fileshandle.setLevel(lvl)
        formatter = logging.Formatter(fmt_str)
        fileshandle.setFormatter(formatter)
        logging.getLogger(logger).addHandler(fileshandle)
        return logging.getLogger(logger)

    @classmethod
    def init_logging(cls, process_name, lvl=logging.INFO, folder="log"):
        fmt_str = '[%(asctime)s][%(levelname)s][%(lineno)d]:%(message)s'
        logging.basicConfig()

        fileshandle = logging.handlers.TimedRotatingFileHandler("./%s/%s.log" % (folder,process_name), when='midnight', interval=1, backupCount=10)
        fileshandle.suffix = "%Y%m%d"
        # fileshandle.setLevel(lvl)
        formatter = logging.Formatter(fmt_str)
        fileshandle.setFormatter(formatter)
        logging.getLogger('').addHandler(fileshandle)
        logging.getLogger('').setLevel(lvl)
    @classmethod
    def strtime2unixtime(cls, strtime):
        Normaltime = datetime.datetime.strptime(strtime,'%Y-%m-%d %H:%M:%S')
        return time.mktime(Normaltime.timetuple())

    @classmethod
    def strdate2unixtime(cls, strtime):
        Normaltime = datetime.datetime.strptime(strtime,'%Y-%m-%d')
        return time.mktime(Normaltime.timetuple())

    @classmethod
    def datetime2strtime(cls, dt):
        timeArray = dt.timetuple()
        otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
        return otherStyleTime

    @classmethod
    def get_datetime(cls):
        timeArray = time.localtime(time.time())
        otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
        return otherStyleTime

    @classmethod
    def get_date(cls, date=None, offset=0):
        if date == None:
            date = time.time()
        if offset != 0:
            date = datetime.datetime.fromtimestamp(date)
            date = time.mktime((date + datetime.timedelta(days=offset)).timetuple())
        timeArray = time.localtime(date)
        otherStyleTime = time.strftime("%Y-%m-%d", timeArray)
        return otherStyleTime

    @classmethod
    def get_date_int(cls):
        timeArray = time.localtime(time.time())
        otherStyleTime = time.strftime("%Y%m%d", timeArray)
        return int(otherStyleTime)

    @classmethod
    def get_datetime_int(cls):
        timeArray = time.localtime(time.time())
        otherStyleTime = time.strftime("%Y%m%d%H%M%S", timeArray)
        return int(otherStyleTime)

    @classmethod
    def is_same_day(cls, stamp1, stamp2):
        return time.localtime(stamp1).tm_mday == time.localtime(stamp2).tm_mday

    @classmethod
    def traceback(cls):
        stack = inspect.stack()
        i = 0
        for frame in stack:
            logging.error("%d %s:%d %s"%(i, frame.filename, frame.lineno, frame.function));

    @classmethod
    def generate_authorization(cls, version, ticket_authver, token_authver, encrypted_token):
        dot = "."
        authorization = version + dot + ticket_authver + dot + token_authver + dot + encrypted_token
        print("authorization = ", authorization)
        return authorization
